﻿package org.sloth.core.move
{
	import flash.geom.Point;
	import flash.utils.getTimer;
	
	import org.sloth.core.timer.TimerMgr;
	import org.sloth.core.timer.TimerVO;
	
	/**
	 * 根据指路线和速度更新坐标位置
	 * 
	 */	
	public class MoveMgr
	{
//============================================================================
//PROPERTY
//============================================================================
		/** 更新间隔（单位：毫秒） */
		public static const INTERVAL:uint = 40;
		
		/** 映射：MoveVO.uid-MoveVO */
		private static const _idMoveVOMap:Object = {};
		/** 映射：MoveVO.uid-InnerVO */
		private static const _idInnerVOMap:Object = {};
//============================================================================
//PUBLIC
//============================================================================
		/**
		 * @param path 移动路径
		 * @param speed 移动速度（单位：px/毫秒）
		 * @param moved_cb 移动完成后回调，参数类型：MoveVO
		 * @param update_cb 移动更新回调，参数类型：MoveVO
		 * @param data 移动过程需要传递的数据
		 * @return 移动动作标识
		 * 
		 */		
		public static function append(path:Array, speed:uint = 50, moved_cb:Function = null, update_cb:Function = null, data:* = null):String
		{
			if (path == null || path.length < 2 || speed == 0) return null;
			
			var moveVO:MoveVO = new MoveVO(path, speed, moved_cb, update_cb, data);
			moveVO.curPosition = path[0];
			_idMoveVOMap[moveVO.uid] = moveVO;
			
			var innerVO:InnerVO = new InnerVO(TimerMgr.addTimer(20, timer_cb, moveVO.uid, 0), 1, getTimer());
			_idInnerVOMap[moveVO.uid] = innerVO;
			
			return moveVO.uid;
		}
		/**
		 * @param id 移动标识
		 */		
		public static function remove(id:String):void
		{
			if (!(id in _idMoveVOMap)) return;
			
			TimerMgr.removeTimer(InnerVO(_idInnerVOMap[id]).timerId);
			delete _idMoveVOMap[id];
			delete _idInnerVOMap[id];
		}
		/**
		 * @param id 移动标识
		 */		
		public static function getVO(id:String):MoveVO
		{
			return _idMoveVOMap[id];
		}
//============================================================================
//PRIVATE
//============================================================================
		private static function update(moveVO:MoveVO):void
		{
			var innerVO:InnerVO = _idInnerVOMap[moveVO.uid];
			
			var timePast:uint = getTimer() - innerVO.lastTime;//距离上次更新过了多长时间
			var distExpected:Number = timePast * moveVO.speed / 1000;//预期应该移动的距离
			var to:Point = moveVO.path[innerVO.index];//下一个目标点
			var distMoved:Number = getDist(moveVO.curPosition, to);//从当前位置到to的距离
			while(distExpected >= distMoved)//如果过了下一个点，更新下一个点
			{
				innerVO.index++;
				moveVO.curPosition = to;
				moveVO.curDirection = getDirect(moveVO.curPosition, to);
				distExpected -= distMoved;
				if (innerVO.index >= moveVO.path.length)
				{
					end(moveVO);
					return;
				}
				to = moveVO.path[innerVO.index];
				distMoved = getDist(moveVO.curPosition, to);
			}
			moveVO.curDirection = getDirect(moveVO.curPosition, to);
			moveVO.curPosition = getPosition(moveVO.curPosition, moveVO.curDirection, distExpected);
			if (moveVO.update_cb != null) moveVO.update_cb(moveVO);
			
			innerVO.lastTime += timePast;
		}
		private static function end(moveVO:MoveVO):void
		{
			remove(moveVO.uid);
			if (moveVO.moved_cb != null) moveVO.moved_cb(moveVO);
		}
		private static function getDist(p1:Point, p2:Point):Number
		{
			var dist:Number = Math.sqrt((p2.y - p1.y) * (p2.y - p1.y) + (p2.x - p1.x) * (p2.x - p1.x));
			return dist;
		}
		private static function getDirect(p1:Point, p2:Point):Number
		{
			return Math.atan2(p2.y - p1.y, p2.x - p1.x);
		}
		private static function getPosition(p1:Point, direction:Number, dist:int):Point
		{
			return new Point(p1.x + dist * Math.cos(direction), p1.y + dist * Math.sin(direction));
		}
//============================================================================
//CALLBACK
//============================================================================
		private static function timer_cb(timerVO:TimerVO):void
		{
			var moveVO:MoveVO = _idMoveVOMap[timerVO.data];
			if (moveVO != null) update(moveVO);
		}
	}
}
class InnerVO
{
//============================================================================
//PROPERTY
//============================================================================
	private var _timerId:String;
	private var _lastTime:uint;
	private var _index:uint;
//============================================================================
//CONSTRUCTOR
//============================================================================
	public function InnerVO(timerId:String, index:uint = 0, lastTime:uint = 0)
	{
		_timerId = timerId;
		_lastTime = lastTime;
		_index = index;
	}
//============================================================================
//getter/setter
//============================================================================
	/** 计时器 timer 标识 */
	public function get timerId():String
	{
		return _timerId;
	}
	/** 记录上一次计算的系统运行时间 */
	public function get lastTime():uint
	{
		return _lastTime;
	}
	/** @private */
	public function set lastTime(value:uint):void
	{
		_lastTime = value;
	}
	/** 当前路线的点序号 */
	public function get index():uint
	{
		return _index;
	}
	/** @private */
	public function set index(value:uint):void
	{
		_index = value;
	}
}